added Feb 2001 SDK
[windows-sources.git] / shared source / sscli20 / tools / resourcecompiler / expeval.c
blob06a9fa7b99f90b36ff7db72b945e5213c2e4354c
1 // ==++==
2 //
3 //
4 // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
5 //
6 // The use and distribution terms for this software are contained in the file
7 // named license.txt, which can be found in the root of this distribution.
8 // By using this software in any fashion, you are agreeing to be bound by the
9 // terms of this license.
10 //
11 // You must not remove this notice, or any other, from this software.
12 //
13 //
14 // ==--==
15 // File: expeval.c
16 // Purpose: Expression Evaluator
17 // ===========================================================================
19 #include <windows.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "expeval.h"
24 #define BUFFER 1024
25 #define MAX_TOKENS 100
27 int LineNumber = 0;
28 TOKEN Tokens[MAX_TOKENS];
30 void
31 ConsumeToken(void)
32 /*++
34 Routine Description:
35 Removes the TOKEN at position 0 in the array from the TOKENs array.
37 Arguments:
38 void
40 Return Value:
41 void
43 --*/
45 int i;
46 for (i=0; Tokens[i].Type!=TK_EOS; i++)
48 Tokens[i] = Tokens[i+1];
50 } //end ConsumeToken
52 int
53 ishex(char p)
55 switch(p)
57 case 'a':
58 case 'A':
59 case 'b':
60 case 'B':
61 case 'c':
62 case 'C':
63 case 'd':
64 case 'D':
65 case 'e':
66 case 'E':
67 case 'f':
68 case 'F':
69 return 1;
70 default:
72 return 0;
76 int
77 LexOneLine(char *p)
78 /*++
79 Routine Description:
80 Analyzes an expression string.
81 Tokenizes the expression converting
82 defined/undefined/unknown macros into TK_TRUE/TK_FALSE/TK_UNKNOWN and
83 ||, &&, (, ) operators into their respective TOKENs. These TOKENs are
84 placed into an array for later expression evaluation.
86 Arguments:
87 *p -- Pointer to line of input to Analyze
88 *strExpr - pointer to store expression for CodeRemoved tag.
90 Return Value:
91 1 if lexer parsed the line, otherwise 0 (i.e. line did not start with a #)
93 --*/
95 int TokensCount = 0;
96 int ParenCheck = 0;
97 int i;
98 char tmp[1024];
99 PTOKEN Token;
101 while (TokensCount <= MAX_TOKENS)
103 i=0;
104 switch(*p) {
106 case ' ':
107 case '\t':
108 case '\r':
109 case '\n':
110 case '\v':
111 case '\f':
112 case '\b':
113 case '\a':
114 case '\\': // line-continuation characters are ignored
115 p++;
116 continue;
118 case '%':
119 Token = &Tokens[TokensCount];
120 Token->Type = TK_MOD;
121 TokensCount++;
122 break;
124 case '+':
125 Token = &Tokens[TokensCount];
126 Token->Type = TK_PLUS;
127 TokensCount++;
128 break;
130 case '-':
131 Token = &Tokens[TokensCount];
132 Token->Type = TK_MINUS;
133 TokensCount++;
134 break;
136 case '*':
137 Token = &Tokens[TokensCount];
138 Token->Type = TK_STAR;
139 TokensCount++;
140 break;
142 case '/':
143 Token = &Tokens[TokensCount];
144 Token->Type = TK_DIVIDE;
145 TokensCount++;
146 break;
148 case '(':
149 Token = &Tokens[TokensCount];
150 Token->Type = TK_LEFT_PAREN;
151 TokensCount++;
152 ParenCheck++;
153 break;
155 case ')':
156 Token = &Tokens[TokensCount];
157 Token->Type = TK_RIGHT_PAREN;
158 TokensCount++;
159 ParenCheck--;
160 break;
162 case '\0':
163 //End of Line. Return
164 if (ParenCheck != 0)
165 return 0;
167 Token = &Tokens[TokensCount];
168 Token->Type = TK_EOS;
169 TokensCount++;
171 return 1;
173 case '0':
174 if (p[1] == 'x' || p[1] == 'X') {
176 // Found '0x' prefix - the token is a hex constant
178 Token = &Tokens[TokensCount];
179 TokensCount++;
180 Token->Type = TK_NUMBER;
182 tmp[i] = *p;
183 p++;
184 i++;
185 tmp[i] = *p;
186 p++;
187 i++;
189 while (isdigit(*p) || ishex(*p)) {
190 tmp[i] = *p;
191 p++;
192 i++;
194 tmp[i] = '\0';
195 Token->Value = strtoul(tmp, NULL, 0);
197 //replace the char
198 continue;
200 } else if (isdigit(p[1])) {
202 // Found '0' followed by a valid number - the token is
203 // an octal constant.
205 Token = &Tokens[TokensCount];
206 TokensCount++;
207 Token->Type = TK_NUMBER;
209 tmp[i] = *p;
210 p++;
211 i++;
212 tmp[i] = *p;
213 p++;
214 i++;
216 while (isdigit(*p)) {
217 tmp[i] = *p;
218 p++;
219 i++;
221 tmp[i] = '\0';
222 Token->Value = strtoul(tmp, NULL, 0);
223 continue;
226 case '1':
227 case '2':
228 case '3':
229 case '4':
230 case '5':
231 case '6':
232 case '7':
233 case '8':
234 case '9':
236 Token = &Tokens[TokensCount];
237 TokensCount++;
238 Token->Type = TK_NUMBER;
240 tmp[i] = *p;
241 p++;
242 i++;
244 while (isdigit(*p)) {
245 tmp[i] = *p;
246 p++;
247 i++;
249 tmp[i] = '\0';
250 Token->Value = strtoul(tmp, NULL, 0);
251 continue;
252 default:
253 return 0;
255 p++;
256 } //end while (TokensCount <= MAX_TOKENS
258 return 0;
259 } //end LexOneLine
261 LONG
262 Expr_Eval(
263 void
266 LONG val = Expr_Eval_1();
270 switch (Tokens[0].Type) {
271 case TK_PLUS:
272 ConsumeToken();
273 val += Expr_Eval_1();
274 break;
276 case TK_MINUS:
277 ConsumeToken();
278 val -= Expr_Eval_1();
279 break;
281 default:
282 return val;
284 } while (1);
287 LONG
288 Expr_Eval_1(
289 void
291 /*++
293 Routine Description:
295 Part of expression evaluator - handles the highest-precedence operators
296 'multiply' and 'divide'.
298 Arguments:
300 None.
302 Return Value:
304 Value of the expression.
306 --*/
308 LONG val = Expr_Eval_2();
312 switch (Tokens[0].Type) {
313 case TK_STAR:
314 ConsumeToken();
315 val *= Expr_Eval_2();
316 break;
318 case TK_DIVIDE:
319 ConsumeToken();
320 val /= Expr_Eval_2();
321 break;
323 case TK_MOD:
324 ConsumeToken();
325 val %= Expr_Eval_2();
326 break;
328 default:
329 // done
330 return val;
332 } while (1);
336 LONG
337 Expr_Eval_2(void)
339 LONG val;
341 switch (Tokens[0].Type) {
342 case TK_NUMBER:
343 val = Tokens[0].Value;
344 ConsumeToken();
345 break;
347 case TK_LEFT_PAREN:
348 ConsumeToken();
349 val = Expr_Eval();
350 ConsumeToken();
351 break;
353 default:
354 val = -1;
355 break;
358 return val;